using System;
using System.Data;
using System.Collections;
using System.ComponentModel;
using System.Threading;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;

namespace needle.UI.Controls.Flat.Windows.Forms
{
	[DefaultEvent("CheckedChanged"),
	 System.ComponentModel.ToolboxItem(true)]
	public class RadioButton : needle.UI.Controls.Flat.Windows.Forms.ControlBase, needle.UI.Controls.Flat.Windows.Forms.IFlashabledControl
	{
		private System.ComponentModel.IContainer components = null;
		private LeftRight m_RadioAlign = LeftRight.Left;
		private bool m_CheckFlash = false;
		private bool m_Checked = false;
		private bool oldCheck = false;
		private bool m_ReadOnly = false;
		private string m_Text = String.Empty;
		private int m_groupIndex = -1;
		//Style Neo, default!!
		private Color m_TextColor = Color.Black;
		private Color m_EditDisabledColor = Color.FromArgb(238, 238, 225);
		private Color m_EditReadOnlyColor = Color.FromArgb(238, 238, 225);
		private Color m_EditFocusedColor = Color.White;
		private Color m_EditColor = Color.FromArgb(242, 242, 228);
		private Color m_FlashColor = Color.FromArgb(170, 170, 221);
		private Color m_ButtonColor = Color.FromArgb(242, 242, 228);
		private Color m_CheckColor = Color.FromArgb(170, 170, 221);

		[Category("Action")]
		public event System.EventHandler CheckedChanged = null;

		#region Constructors

		public RadioButton()
		{
			InitializeComponent();
		}

		#endregion

		#region Dispose

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#endregion

		#region Component Designer generated code
		private void InitializeComponent()
		{
			// 
			// EnterpriseRadioButton
			// 
			this.Name = "RadioButton";
			this.Size = new System.Drawing.Size(168, 19);
			this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RadioButton_MouseUp);
			this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.RadioButton_KeyUp);
		}
		#endregion

		#region Events handlers
		
		private void RadioButton_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			if(!this.ReadOnly && e.KeyData == Keys.Space)
			{
				if(!this.Checked)
				{
					this.Checked = true;
					//OnCheckedChanged();
				}
			}
		}
		
		private void RadioButton_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(!this.ReadOnly)
			{
				if(!this.Checked)
				{
					this.Checked = true;
				}

				if (this.Checked != this.oldCheck) 
				{
					this.oldCheck = this.Checked;
					//OnCheckedChanged();
				}
			}
		}

		#endregion

		#region Virtuals

		protected void OnCheckedChanged(EventArgs e)
		{
			if(this.CheckedChanged != null)
			{
				this.CheckedChanged(this,e);
			}
		}

		#endregion

		#region Overrides

		protected override void DrawControl(Graphics g,bool hot)
		{

			using (Pen pen = new Pen(base.Style!=null?base.Style.InteliBorderColor(hot):StyleGuide.InteliBorderColor(hot, base.BorderHotColor, base.BorderColor)))
			{
				using (Brush brush1 = new SolidBrush(this.EditFocusedColor),
					         brush2 = new SolidBrush(base.Style!=null?
									  base.Style.InteliEditColor(this.ReadOnly,this.Enabled):
									  StyleGuide.InteliEditColor(this.ReadOnly,this.Enabled, this.EditColor, this.EditReadOnlyColor, this.EditDisabledColor)),
						     brush3 = new SolidBrush(this.Enabled ? this.CheckColor : Color.Silver),
						     brush4 = new SolidBrush(m_Checked ? this.ButtonColor : this.FlashColor),
						     brush5 = new SolidBrush(this.TextColor))
				{
				
					//g.Clear(this.ButtonColor);
					this.BackColor = this.ButtonColor;
			
					Rectangle checkRect = CheckRect();

					if(this.Focused)
					{
						g.FillEllipse(brush1,checkRect);
					}
					else
					{
						g.FillEllipse(brush2,checkRect);
					}

					g.DrawEllipse(pen,checkRect);

					if (!m_CheckFlash)
					{
						if(m_Checked)
						{
							Rectangle drawRect = new Rectangle(checkRect.Left + 1,checkRect.Top + 1, 7, 7);
							g.FillEllipse(brush3, drawRect);
						}
					}
					else
					{
						Rectangle drawRect = new Rectangle(checkRect.Left + 1,checkRect.Top + 1, 7, 7);
						g.FillEllipse(brush4, drawRect);
					}
			
					StringFormat format  = new StringFormat();
					format.LineAlignment = StringAlignment.Center;
					format.Alignment     = StringAlignment.Near;
					format.HotkeyPrefix  = HotkeyPrefix.Show;

					Rectangle txtRect = new Rectangle(this.ClientRectangle.Left + 
						checkRect.Right + 2,
						this.ClientRectangle.Top-1,
						this.ClientRectangle.Right,
						this.ClientRectangle.Bottom);

					g.DrawString(m_Text,this.Font,brush5,txtRect,format);
				}
			}
		}		

		protected override bool ProcessMnemonic(char charCode)
		{
			if (this.CanSelect && IsMnemonic(charCode, m_Text))
			{
				if(!this.Checked)
				{
					this.Checked = true;
					//OnCheckedChanged();
				}
				//
				this.Focus();
				return true;
			}
			else {return false;}
		}

		protected override void OnStyleChanged(object sender, StyleEventArgs args)
		{
			base.OnStyleChanged(sender, args);

			if (args.PropertyName == "TextColor") {this.TextColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "FlashColor") {this.m_FlashColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "RadioButtonColor") {this.m_ButtonColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "CheckColor") {this.m_CheckColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditColor") {this.m_EditColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditFocusedColor") {this.m_EditFocusedColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditReadOnlyColor") {this.m_EditReadOnlyColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditDisabledColor") {this.m_EditDisabledColor = (Color)args.PropertyValue;}

			this.Invalidate(true);
		}

		protected override void OnPlansOfColorsChanged(object sender, PlansOfColorsChangedEventArgs args)
		{
			base.OnPlansOfColorsChanged(sender, args);

			if (this.Style!=null)
			{
				this.TextColor = this.Style.TextColor;
				this.m_FlashColor = this.Style.FlashColor;
				this.m_ButtonColor = this.Style.RadioButtonColor;
				this.m_CheckColor = this.Style.CheckColor;
				this.m_EditColor = this.Style.EditColor;
				this.m_EditFocusedColor = this.Style.EditFocusedColor;
				this.m_EditReadOnlyColor = this.Style.EditReadOnlyColor;
				this.m_EditDisabledColor = this.Style.EditDisabledColor;
			}

			this.Invalidate(true);
		}

		#endregion

		#region Internal helpers

		private Rectangle CheckRect()
		{
			Rectangle rect;
			if(m_RadioAlign == LeftRight.Left)
			{
				rect = new Rectangle(0,(this.Height - 10)/2,9,9);
			}
			else
			{
				rect = new Rectangle((this.Width - 9)/2,(this.Height - 9)/2,9,9);
			}			
			return rect;
		}

		private void ThreadFlashControl()
		{
			for (int i=1; i<=8;i++)
			{
				m_CheckFlash = !m_CheckFlash;
				this.Invalidate();
				
				Thread.Sleep(150);
			}
			m_CheckFlash = false;
		}

		#endregion

		#region Properties

		[Category("Style")]
		public Color TextColor
		{
			get {return m_TextColor;}
			set 
			{
				m_TextColor = value;
				this.ForeColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color FlashColor
		{
			get {return m_FlashColor;}
			set 
			{
				m_FlashColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonColor
		{
			get {return m_ButtonColor;}
			set 
			{
				m_ButtonColor = value;
				this.BackColor = m_ButtonColor;
				this.Invalidate();
			}
		}

		[Browsable(false)]
		public override Color ForeColor
		{
			get {return m_TextColor;}
			set 
			{
				m_TextColor  = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditColor
		{
			get {return m_EditColor;}
			set 
			{
				m_EditColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditFocusedColor
		{
			get {return m_EditFocusedColor;}
			set 
			{
				m_EditFocusedColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditReadOnlyColor
		{
			get {return m_EditReadOnlyColor;}
			set 
			{
				m_EditReadOnlyColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditDisabledColor
		{
			get {return m_EditDisabledColor;}
			set 
			{
				m_EditDisabledColor = value;
				this.Invalidate();
			}
		}
		
		[Category("Style")]
		public Color CheckColor
		{
			get {return m_CheckColor;}
			set 
			{
				m_CheckColor = value;
				this.Invalidate();
			}
		}

		[MergableProperty(false),
		 Bindable(true),
		 Category("Appearance")]
		public bool Checked
		{
			get {return m_Checked;}

			set
			{
				m_Checked = value;
				this.OnCheckedChanged(new EventArgs());

				if (m_Checked && this.Parent != null)
				{
					foreach (Control currentControl in this.Parent.Controls)
					{
						if (currentControl is RadioButton && 
							currentControl != this &&
							((RadioButton)currentControl).GroupIndex == this.GroupIndex) 
						{
							((RadioButton)currentControl).Checked = false;	
						}
					}
				}

				this.Invalidate(false);				
			}
		}

		[Category("Behavior")]
		public bool ReadOnly
		{
			get {return m_ReadOnly;}
			set
			{
				m_ReadOnly = value;
				this.Invalidate(false);
			}
		}

		[Browsable(true),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
		Category("Appearance"),
		Bindable(true)]
		public override string Text
		{
			get {return m_Text;}
			set
			{
				m_Text = value;
				this.Invalidate();
			}
		}

		[Browsable(true),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
		Category("Behavior")]
		public int GroupIndex
		{
			get{return m_groupIndex;}
			set{m_groupIndex = value;}
		}
		
		#endregion

		#region IFlashabledControl

		public void FlashControl()
		{
			Thread m_Thread = new Thread(new ThreadStart(ThreadFlashControl));
			m_Thread.Start();
		}
		
		#endregion
	}
}